package com.shop.cereshop.commons.utils.redis;

import lombok.SneakyThrows;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @description: Redisson工具类
 * @author zdd
 * @date 2022/1/14 11:12
 * @version 1.0
 */
@Component
public class RedissonUtil {

    private static RedissonClient redissonClient;

    @Autowired
    public RedissonUtil(RedissonClient redissonClient) {
        RedissonUtil.redissonClient = redissonClient;
    }


    // ============================ ↓↓↓↓↓↓ 操作 锁 ↓↓↓↓↓↓ ============================

    /**
     * 可重入锁
     * 看门狗机制：不设置leaseTime值时触发
     *
     * @param key key
     * @return 锁
     */
    public static RLock getLock(String key) {
        return redissonClient.getLock(key);
    }

    /**
     * 可重入锁
     *
     * @param key       key
     * @param leaseTime 时间
     * @param unit      时间单位
     * @return 锁
     */
    public static RLock lock(String key, long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getLock(key);
        // 加锁leaseTime以后自动解锁
        // 无需调用unlock方法手动解锁
        lock.lock(leaseTime, unit);
        return lock;
    }

    /**
     * 可重入锁
     *
     * @param key       key
     * @param waitTime  最多等待时间。 尝试获取锁的最大等待时间，超过这个值，则认为获取锁失败
     * @param leaseTime 持有锁的时间 锁的持有时间,超过这个时间锁会自动失效（值应设置为大于业务处理的时间，确保在锁有效期内业务能处理完）
     * @param unit      时间单位
     * @return 锁
     */
    @SneakyThrows(Exception.class)
    public static RLock tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) {
        RLock lock = redissonClient.getLock(key);
        // 如果超时没有释放锁，则智能地自动释放锁
        lock.tryLock(waitTime, leaseTime, unit);
        return lock;
    }

}
